package com.czk.classreader.method;

import com.czk.utils.FileUtil;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;

/**
 * @Author:ChenZhangKun
 * @Date: 2021/8/25 17:18
 */
public class MethodReplaceInvokeCore {
    public static void main(String[] args) {
        String path = "F:\\IdeaProjects\\asm\\target\\classes\\com\\czk\\sample\\HelloWorld.class";
        byte[] bytes = FileUtil.readBytes(path);
        ClassReader cr = new ClassReader(bytes);
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
        int api = Opcodes.ASM9;
        // 替换静态方法
        ClassVisitor cv = new MethodReplaceInvokeVisitor(api, cw, "java/lang/Math", "max", "(II)I",
                Opcodes.INVOKESTATIC, "java/lang/Math", "min", "(II)I");
        // 对于non-static方法来说，它有一个隐藏的this变量。我们在替换non-static方法的时候，要把this变量给“消耗”掉。
        // 这里就是定义了一个方法入参为PrintStream的把opreateStack里面的PrintStream消耗了
        ClassVisitor cvv = new MethodReplaceInvokeVisitor(api, cw, "java/io/PrintStream", "println", "(I)V",
                Opcodes.INVOKESTATIC, "com/czk/utils/PrintUtil", "output", "(Ljava/io/PrintStream;I)V");
        //（4）结合ClassReader和ClassVisitor
        int parsingOptions = ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES;
        cr.accept(cv, parsingOptions);

        //（5）生成byte[]
        byte[] bytes2 = cw.toByteArray();

        FileUtil.writeBytes(path, bytes2);
    }
}
